PDF 10 / 10
Contents

Kubernetes Concepts

Select topics to study or include in your quiz. Expand groups to see subtopics.

PDFs 1–10 loaded 10 of N modules
Kubernetes Components PDF 1 2 subtopics
Control Plane Components — kube-apiserver, etcd, kube-scheduler, kube-controller-manager, cloud-controller-manager
Node Components — kubelet, kube-proxy, Container runtime
Component Reference Details
kube-apiserver — core server, exposes Kubernetes HTTP API
etcd — consistent, highly-available key-value store
kube-scheduler — assigns Pods to nodes
kube-controller-manager — runs controller loops
cloud-controller-manager — cloud provider integration (optional)
kubelet — node agent, ensures Pods run
kube-proxy — network proxy on each node
Container runtime — runs containers (containerd, CRI-O, etc.)
📦
Objects in Kubernetes PDFs 2–6 9 subtopics
Understanding Kubernetes Objects — persistent entities, desired state, spec & status, record of intent
Describing Objects (Manifests) — required fields, YAML/JSON, apiVersion, kind, metadata, spec
Object Management Techniques — imperative commands, imperative config, declarative config, trade-offs
Object Names and IDs — name uniqueness, DNS subdomain, RFC 1123/1035 label names, path segment names, UIDs
Labels & Equality-based Selectors — key/value pairs, motivation, syntax, =, ==, != operators
Set-based Selectors & API Filtering — in, notin, exists operators; LIST/WATCH query params; matchLabels & matchExpressions
Set References in API Objects — Service/ReplicationController selectors; Job/Deployment/ReplicaSet/DaemonSet matchExpressions; node selection
Using Labels Effectively — multi-label strategies, guestbook example, slicing by dimension, app.kubernetes.io/name convention
Updating Labels — kubectl label command, -L / --label-columns flag, relabeling existing resources
Key Concepts Reference
spec — desired state you provide; status — current state, maintained by K8s
apiVersion, kind, metadata, spec — 4 required manifest fields
Imperative commands — operate on live objects, no history
Declarative config — kubectl detects create/update/delete, works on directories, uses patch
Name — unique per resource type within namespace; UID — unique across cluster lifetime, never reused
Equality-based: =, ==, != operators; Set-based: in, notin, exists operators; comma = AND
matchLabels — map of key/value pairs (equality); matchExpressions — list with key, operator, values
Service/RC — only equality-based selectors; Job/Deployment/ReplicaSet/DaemonSet — support set-based
Multi-label strategy — use multiple labels to slice resources by app, tier, role; enables cross-cutting queries
app.kubernetes.io/name — recommended label key for tooling/automation; app — for convenience in manual CLI queries
kubectl label — updates labels on existing resources; -L / --label-columns — shows label values as columns in output
🗂
Namespaces PDF 7 4 subtopics
Namespace Concepts & When to Use — isolation, scope for names, multiple teams, resource quota, not for versions
Initial Namespaces — default, kube-node-lease, kube-public, kube-system; kube- prefix reserved
Working with Namespaces — kubectl get namespace, --namespace flag, config set-context, DNS pattern, automatic labelling
Namespaces and DNS / Scope — DNS form service-name.namespace.svc.cluster.local, FQDN, cluster-scoped resources (Nodes, PersistentVolumes)
Key Concepts Reference
default — start without creating a namespace; kube-system — K8s system objects
kube-public — readable by all clients incl. unauthenticated; kube-node-lease — Lease objects for heartbeats
Namespaces cannot be nested; each resource can only be in one namespace
DNS pattern: service-name.namespace-name.svc.cluster.local
Cluster-scoped (NOT in namespace): Nodes, PersistentVolumes, StorageClass, Namespace itself
kubernetes.io/metadata.name — auto-set immutable label on every namespace (stable since 1.22)
🏷
Annotations & Field Selectors PDFs 8–9 5 subtopics
Annotations — non-identifying metadata, labels vs annotations, use cases, syntax, string-only values
Field Selectors — select by resource field value, supported operators =, ==, !=, supported fields per kind
Chained & Multi-type Field Selectors — comma-chaining, multiple resource types, metadata.name and metadata.namespace universal fields
Recommended Labels — app.kubernetes.io/* prefix, 6 standard keys (name, instance, version, component, part-of, managed-by), WordPress/MySQL examples
Storage Versions — API storage version, automatic conversion, 1 active storage version per resource, CRD storage version, encryption at rest
Key Concepts Reference
Annotations — non-identifying metadata; labels = select/find; annotations = store arbitrary info
Annotation values must be strings — no booleans, numbers, lists
Field selectors — filter by actual resource field values (not labels); supports =, ==, !=
Universal fields: metadata.name and metadata.namespace supported by all resource types
Set-based operators (in, notin, exists) are NOT supported for field selectors
app.kubernetes.io/* — shared prefix for recommended labels; 6 keys: name, instance, version, component, part-of, managed-by
Storage version — 1 active per resource at a time; reads auto-convert; writes use current storage version
CRDs must explicitly mark one version as storage: true; only one version can be storage at a time
🔌
The Kubernetes API PDF 10 4 subtopics
API Overview & Discovery — API server role, Discovery API (name/scope/URL/verbs), aggregated vs unaggregated, /api and /apis endpoints
OpenAPI & Protobuf — OpenAPI v2 (/openapi/v2), OpenAPI v3 (/openapi/v3, stable since 1.27), Protobuf serialization, /openapi/v3/apis/<group>/<version>
API Groups, Versioning & Changes — multiple API paths (/api/v1, /apis/rbac…/v1alpha1), versioning at API level, alpha/beta/GA compatibility, deprecation policy
API Extension — two extension mechanisms: Custom Resources (CRDs) and aggregation layer
Key Concepts Reference
Discovery API — brief summary: name, scope, URL, verbs; NOT full schema
Aggregated discovery — /api and /apis, stable v1.30; reduces request count
OpenAPI v3 — preferred (lossless); v2 drops default/nullable/oneOf; both served
Versioning at API level not resource/field; path-based: /api/v1, /apis/group/version
GA (v1) — strong compatibility; beta — data preserved, must transition; alpha — may break
Persistence: Kubernetes stores serialized state in etcd
🔧
Workloads & Controllers PDF 5+ Coming soon
🌐
Networking & Services PDF 6+ Coming soon
0 topics selected
Section 1 · PDF 1

Kubernetes Components

A Kubernetes cluster consists of a control plane and one or more worker nodes. The control plane manages overall cluster state; nodes run the actual workloads.

Mental Model

Think of the control plane as the brain (makes decisions) and nodes as the muscles (do the work).

Control Plane Worker Nodes etcd kubelet kube-proxy
Section 1.1

Control Plane Components

The control plane manages the overall state of the cluster — making global decisions (like scheduling) and detecting/responding to cluster events.

ComponentRoleKey fact
kube-apiserver Exposes the Kubernetes HTTP API Front-end for the control plane; all kubectl commands go here first
etcd Persistent key-value store Stores ALL cluster data; consistent & highly-available
kube-scheduler Assigns Pods to nodes Watches for new Pods with no assigned node
kube-controller-manager Runs controller loops Implements K8s API behavior (Node, Job, EndpointSlice controllers…)
cloud-controller-manager Integrates with cloud providers Optional — only in cloud deployments

kube-apiserver

The core component that exposes the Kubernetes HTTP API. It's the single entry point for all cluster operations. Designed to scale horizontally — you can run multiple instances.

etcd

A consistent, highly-available key-value store used as Kubernetes' backing store for all cluster data. If you run Kubernetes in production, always have a backup plan for etcd.

kube-scheduler

Watches for newly created Pods that have no assigned node and selects a node for them to run on. Factors considered include: resource requirements, hardware/software/policy constraints, affinity/anti-affinity rules, data locality, and deadlines.

kube-controller-manager

Runs controller processes. Each controller is a separate control loop, but compiled into one binary for simplicity. Examples:

  • Node controller — notices when nodes go down
  • Job controller — watches Job objects, creates Pods
  • EndpointSlice controller — links Services to Pods
  • ServiceAccount controller — manages default accounts

cloud-controller-manager (optional)

Embeds cloud-specific control logic. Lets you link your cluster to your cloud provider's API. Only runs if you're using a cloud provider. Includes:

  • Node controller — checking cloud provider for node deletion
  • Route controller — setting up cloud network routes
  • Service controller — managing cloud load balancers
Memory Tip

APIserver → etcd → Scheduler → Controller = AESC — "Always Ensuring Stable Clusters"

⚡ Quick Check — Control Plane

Which control plane component is responsible for assigning unscheduled Pods to nodes?

kube-scheduler watches for Pods with nodeName: "" and assigns them to a suitable node based on resource availability, constraints, and policies.
Section 1.2

Node Components

Node components run on every worker node, maintaining running Pods and providing the Kubernetes runtime environment.

ComponentRoleKey fact
kubelet Node agent Ensures containers in Pods are running & healthy. Does NOT manage containers not created by K8s.
kube-proxy Network proxy Implements the Service concept by maintaining network rules. Uses OS packet filtering if available.
Container runtime Runs containers Any CRI-compliant runtime: containerd, CRI-O, etc.

kubelet

An agent that runs on each node. Takes a set of PodSpecs (provided via various mechanisms) and ensures the containers described are running and healthy.

Important distinction

The kubelet only manages containers created through Kubernetes. It does not manage containers you start manually on the node.

kube-proxy

A network proxy that runs on each node, implementing part of the Kubernetes Service concept. Maintains network rules that allow network communication to Pods from inside or outside the cluster.

Uses the OS packet filtering layer (e.g., iptables or ipvs) when available; otherwise forwards traffic itself.

Container Runtime

The fundamental component that empowers Kubernetes to run containers. Kubernetes supports any runtime implementing the Kubernetes CRI (Container Runtime Interface).

containerd CRI-O Any CRI-compatible
⚡ Quick Check — Node Components

A developer manually starts a container on a worker node using docker run (bypassing Kubernetes). Will kubelet manage this container?

kubelet only manages containers created through Kubernetes (via PodSpecs). Containers started manually on the node are invisible to it.
Section 1.3 · Summary

Architecture at a Glance

Full Picture

Every request flows: kubectlkube-apiserveretcd (persist). Then controllers react, scheduler assigns, kubelet starts containers.

LayerComponentsLives on
Control Planeapiserver, etcd, scheduler, controller-manager, (cloud-controller-manager)Dedicated control node(s)
Worker Nodekubelet, kube-proxy, container runtimeEvery worker node
Optional Add-onsDNS, Dashboard, networking plugins, storage pluginsCluster-wide

Key Relationships

  • apiserver ↔ etcd: The apiserver is the only component that writes to etcd
  • scheduler → apiserver: Scheduler watches the apiserver for unbound Pods
  • controller-manager → apiserver: Controllers use the apiserver to observe and act
  • kubelet → apiserver: Each kubelet registers with and reports to the apiserver
  • kube-proxy → apiserver: kube-proxy watches Services and Endpoints via the apiserver
⚡ Quick Check — Architecture

Which is the ONLY component that directly reads/writes to etcd?

✓ Only kube-apiserver reads/writes etcd directly. All other components interact with cluster state through the apiserver, never etcd directly.
Section 2 · PDF 2

Objects in Kubernetes

Kubernetes objects are persistent entities in the Kubernetes system. Kubernetes uses them to represent the state of your cluster. Specifically, they can describe:

  • What containerized applications are running (and on which nodes)
  • The resources available to those applications
  • The policies around how those applications behave — restart policies, upgrades, fault-tolerance
Record of Intent

A Kubernetes object is a "record of intent" — once you create the object, Kubernetes will constantly work to ensure that the object exists. By creating an object, you're telling Kubernetes the desired state you want.

To work with Kubernetes objects — create, modify, or delete — you use the Kubernetes API. The kubectl CLI makes the necessary API calls for you. You can also use the API directly via Client Libraries.

Persistent entities Desired state Kubernetes API kubectl
Section 2.1

Object Spec and Status

Almost every Kubernetes object includes two nested object fields that govern the object's configuration:

FieldWhat it isWho sets it
spec Desired state — the characteristics you want the resource to have You (the user), when you create/update the object
status Current state — describes the actual state of the object Kubernetes system (supplied and updated continuously)
Concrete Example

You create a Deployment with spec.replicas: 3 — Kubernetes starts 3 Pods and updates status to reflect this. If one Pod fails (status changes), Kubernetes reconciles by starting a replacement to match spec.

The Kubernetes control plane continually and actively manages every object's actual state to match the desired state you supplied.

⚡ Quick Check — Spec vs Status

You have a Deployment with spec.replicas: 3. One Pod crashes. What does Kubernetes do?

✓ Kubernetes reconciles spec vs status. Since spec says 3 and status shows 2, the controller starts a new Pod to reach the desired count. Spec is never auto-modified to match failures.
Section 2.2

Describing a Kubernetes Object (Manifests)

When you create an object, you provide a manifest — a file (typically YAML) that includes the object spec describing its desired state, plus basic identification. Kubernetes manifests are YAML by convention (JSON also supported).

The 4 Required Fields

apiVersion kind metadata spec
FieldPurposeExample
apiVersionWhich version of the Kubernetes API you're using to create this objectapps/v1, v1
kindWhat kind of object you want to createDeployment, Pod, Service
metadataData that helps uniquely identify the object — name, UID, optional namespacename: nginx-deployment
specWhat state you desire for the object (format varies per object type)replicas: 2

Example Deployment Manifest

apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 # tells deployment to run 2 pods template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80

Applying a Manifest

kubectl apply -f https://k8s.io/examples/application/deployment.yaml # Output: deployment.apps/nginx-deployment created

Server-Side Field Validation

Starting with Kubernetes v1.25, the API server offers server-side field validation that detects unrecognized or duplicate fields in an object. It provides all the functionality of kubectl --validate on the server side.

# --validate accepts: ignore, warn, strict (true=strict, false=ignore) kubectl apply -f manifest.yaml --validate=strict # default kubectl apply -f manifest.yaml --validate=warn # warn but proceed kubectl apply -f manifest.yaml --validate=ignore # skip validation
⚡ Quick Check — Required Fields

Which field in a Kubernetes manifest specifies the desired state of the object?

spec describes the desired state you want for the object. metadata identifies it, kind names the object type, apiVersion specifies the API version.
Section 2.3

Kubernetes Object Management

The kubectl tool supports three different ways to create and manage objects. Warning: use only one technique per object — mixing techniques causes undefined behavior.

TechniqueOperates onRecommended envWritersLearning curve
Imperative commandsLive objectsDevelopment1+Lowest
Imperative object configIndividual filesProduction1Moderate
Declarative object configDirectories of filesProduction1+Highest
Warning

A Kubernetes object should be managed using only one technique. Mixing and matching techniques for the same object results in undefined behavior.

Section 2.3a

Imperative Commands & Configuration

Imperative Commands

The user operates directly on live objects in a cluster. Operations are provided to kubectl as arguments or flags. Recommended for getting started or running one-off tasks — provides no history of previous configurations.

# Run an instance of the nginx container kubectl create deployment nginx --image nginx
✓ Simple single action word ✓ Single step to make changes ✗ No change review process ✗ No audit trail ✗ No template for new objects

Imperative Object Configuration

The kubectl command specifies the operation (create, replace, etc.) plus at least one file name. The file must contain a full definition of the object in YAML or JSON format.

# Create objects defined in a file kubectl create -f nginx.yaml # Delete objects from two files kubectl delete -f nginx.yaml -f redis.yaml # Update/overwrite the live config with file kubectl replace -f nginx.yaml
Warning — replace

The replace command replaces the existing spec with the newly provided one, dropping all changes missing from the file. Do not use with resource types whose specs are updated independently (e.g., LoadBalancer Services have their externalIPs updated by the cluster).

✓ Stored in source control (Git) ✓ Integrates with change review ✓ Template for new objects ✗ Requires object schema knowledge ✗ Works best on files, not dirs ✗ Live edits lost on next replace
Section 2.3b

Declarative Object Configuration

The user operates on object configuration files stored locally but does NOT define the operations to be taken. Create, update, and delete operations are automatically detected per-object by kubectl. Enables working on directories where different operations might be needed for different objects.

# Process all configs in a directory, preview first kubectl diff -f configs/ kubectl apply -f configs/ # Recursively process directories kubectl diff -R -f configs/ kubectl apply -R -f configs/
Key Advantage

Declarative config uses the patch API operation to write only observed differences — instead of replacing the entire object. This means changes made by other writers (e.g. autoscalers) are retained even if not in the config file.

✓ Live object changes retained ✓ Works on directories ✓ Auto-detects create/patch/delete ✗ Harder to debug ✗ Partial updates create complex merges

Comparison Summary

ConcernImperative cmdImp. configDeclarative
Source control
Audit trail
Retains live changesN/A
Works on directories
Learning curveLowestModerateHighest
Debug complexityLowLowHigh
⚡ Quick Check — Management Techniques

You're running a LoadBalancer Service. Its externalIPs field is automatically updated by the cluster. Which command should you AVOID when updating this Service?

kubectl replace replaces the entire spec with what's in the file, dropping the cluster-managed externalIPs field. Use kubectl apply (patch-based) or kubectl patch for targeted updates instead.
Section 2.4 · PDF 3

Object Names and IDs

Each object in your cluster has a Name that is unique for that type of resource. Every Kubernetes object also has a UID that is unique across your whole cluster.

For non-unique user-provided attributes, Kubernetes provides labels and annotations.

Key distinction

Name — unique per resource type within a namespace (client-provided, reusable after deletion). UID — globally unique across the entire cluster lifetime (system-generated, never reused).

Names

A Name is a client-provided string that refers to an object in a resource URL — e.g., /api/v1/pods/some-name.

  • Only one object of a given kind can have a given name at a time
  • If you delete an object, you can create a new one with the same name
  • Names must be unique across all API versions of the same resource (API version is irrelevant for uniqueness — it's API group + resource type + namespace + name)
Physical entity note

If a Node representing a physical host is re-created under the same name without deleting the old Node object, Kubernetes treats the new host as the old one — this can cause inconsistencies.

generateName

When generateName is provided instead of name, the server uses the value as a name prefix and appends a generated suffix. Since Kubernetes v1.31, the server makes up to 8 attempts to generate a unique name before returning an HTTP 409 response.

Four Name Constraint Types

Constraint typeMax lengthCharacters allowedStart/End
DNS Subdomain 253 chars lowercase alphanumeric, -, . alphanumeric
RFC 1123 Label 63 chars lowercase alphanumeric, - alphanumeric
RFC 1035 Label 63 chars lowercase alphanumeric, - must start with alphabetic character
Path Segment varies cannot be . or .., cannot contain / or %

DNS Subdomain Names (most common)

Required by most resource types (Deployments, ConfigMaps, etc.). Must:

  • Contain no more than 253 characters
  • Contain only lowercase alphanumeric characters, -, or .
  • Start and end with an alphanumeric character

RFC 1123 Label Names

Used by some resource types. Must:

  • Contain at most 63 characters
  • Contain only lowercase alphanumeric characters or -
  • Start and end with an alphanumeric character
Exception

When RelaxedServiceNameValidation feature gate is enabled, Service object names are allowed to start with a digit.

RFC 1035 Label Names

Same as RFC 1123 but must start with an alphabetic character (not a digit). Used by some specific resource types.

Path Segment Names

Some resource types require names to be safely encodable as a path segment. The name:

  • May not be . or ..
  • May not contain / or %
# Valid path segment name example apiVersion: v1 kind: Pod metadata: name: nginx-demo # valid: no /, %, ., .. spec: containers: - name: nginx image: nginx:1.14.2

UIDs

A Kubernetes UID is a system-generated string that uniquely identifies objects. Every object created over the whole lifetime of a cluster has a distinct UID — intended to distinguish between historical occurrences of similar entities.

  • UIDs are universally unique identifiers (UUIDs)
  • Standardized as ISO/IEC 9834-8 and ITU-T X.667
  • System-generated — not set by users
  • Never reused, even if an object with the same name is recreated
Name vs UID mental model

Think of Name like a username (unique now, can be reused after account deletion) and UID like a social security number (unique forever, never reassigned).

⚡ Quick Check — Names & UIDs

You delete a Pod named my-pod and create a new Pod with the same name. The new Pod will have:

Same Name, new UID. Names can be reused after an object is deleted. UIDs are never reused — the new Pod gets a fresh system-generated UUID to distinguish it from the historical deleted Pod.
⚡ Quick Check — Name Constraints

A ConfigMap name must conform to DNS subdomain rules. Which of these names is INVALID?

MyConfig is invalid — DNS subdomain names must contain only lowercase alphanumeric characters. Uppercase letters are not allowed.
Section 2.5 · PDF 4

Labels

Labels are key/value pairs attached to objects such as Pods. They specify identifying attributes that are meaningful and relevant to users, but do not directly imply semantics to the core system.

Labels can be used to organize and to select subsets of objects. Labels can be attached at creation time and modified at any time. Each object can have a set of key/value labels; each key must be unique per object.

"metadata": { "labels": { "key1" : "value1", "key2" : "value2" } }
Labels vs Annotations

Labels are for identifying attributes used in queries and selection. Non-identifying information (build metadata, tool info, etc.) should use annotations instead.

Motivation

Labels enable users to map their own organizational structures onto system objects in a loosely coupled fashion, without requiring clients to store those mappings.

Service deployments and batch processing pipelines are often multi-dimensional entities — multiple partitions or deployments, release tracks, tiers, micro-services. Management often requires cross-cutting operations, which breaks encapsulation of strictly hierarchical representations.

Common label examples

release: stable / canary environment: dev / qa / production tier: frontend / backend / cache partition: customerA / customerB track: daily / weekly

Syntax and character set

Label keys have two segments: an optional prefix and a name, separated by a slash (/).

SegmentRules
Name (required) ≤63 characters; start and end with alphanumeric [a-z0-9A-Z]; may contain dashes, underscores, dots between
Prefix (optional) DNS subdomain ≤253 chars, followed by /. If omitted, key is private to the user
System component rule

Automated system components (kube-scheduler, kube-controller-manager, kube-apiserver, kubectl, or third-party automation) that add labels to end-user objects must specify a prefix. The kubernetes.io/ and k8s.io/ prefixes are reserved for Kubernetes core components.

Valid label values

  • Must be 63 characters or less (can be empty)
  • Unless empty, must begin and end with an alphanumeric character [a-z0-9A-Z]
  • Could contain dashes (-), underscores (_), dots (.), and alphanumerics between

Example manifest with labels

apiVersion: v1 kind: Pod metadata: name: label-demo labels: environment: production app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
⚡ Quick Check — Labels

Which label key is VALID according to Kubernetes label syntax rules?

app.kubernetes.io/version — valid prefix (app.kubernetes.io is a DNS subdomain) + valid name (version). The first has two slashes (invalid). MY_LABEL has uppercase (invalid for the name segment if mixing — actually uppercase IS allowed in names). -starts-with-dash starts with a dash (must start with alphanumeric).
Section 2.6

Label Selectors

Unlike names and UIDs, labels do not provide uniqueness — we expect many objects to carry the same labels. Via a label selector, the client can identify a set of objects. The label selector is the core grouping primitive in Kubernetes.

The API supports two types of selectors: equality-based and set-based. A selector can be made of multiple requirements, comma-separated. All requirements must be satisfied — the comma acts as a logical AND (&&) operator.

Caution — no OR operator

For both equality-based and set-based conditions, there is no logical OR (||) operator. Ensure your filter statements are structured accordingly.

ReplicaSet selector overlap

For some API types such as ReplicaSets, the label selectors of two instances must not overlap within a namespace — the controller would see conflicting instructions and fail to determine how many replicas should be present.

Equality-based requirements

Allow filtering by label keys and values. Three operators: =, == (synonyms for equality) and != (inequality).

# Select all resources with environment=production AND tier≠frontend environment = production tier != frontend # Comma is AND — combined in one selector: environment=production,tier!=frontend

The != operator also selects resources with no labels with the given key at all. One usage scenario: node selection criteria. Example selects nodes where accelerator=nvidia-tesla-p100:

apiVersion: v1 kind: Pod spec: nodeSelector: accelerator: nvidia-tesla-p100
Memory anchor — selector types

Equality-based = simple key/value match with =, ==, !=.
Set-based = match against a set of values with in, notin, exists.
Comma always means AND — there is no OR.

⚡ Quick Check — Selectors

What does the selector environment=production,tier!=frontend match?

✓ Comma = logical AND. Both conditions must be satisfied. The != operator also matches objects that have no "tier" label at all — not just those with tier≠frontend.
Section 2.7 · PDF 5

Set-based Selectors

Set-based label requirements allow filtering keys according to a set of values. Three operators are supported: in, notin, and exists (key identifier only).

# in — key must match one of the values environment in (production, qa) # notin — key must NOT match any of the values (also matches if key is absent) tier notin (frontend, backend) # exists — key must exist (no value check) partition # !exists — key must NOT exist !partition
ExpressionMeaning
environment in (production, qa)key=environment, value is production or qa
tier notin (frontend, backend)value is NOT frontend or backend, OR key is absent
partitionkey=partition exists; no value restriction
!partitionkey=partition must NOT exist; no value check
Set-based vs Equality-based

Set-based is a superset of equality-based. For example, environment=production is equivalent to environment in (production). Similarly, != is equivalent to notin. Set-based requirements can be mixed with equality-based in the same selector.

Mixing selector types

Set-based and equality-based requirements can be combined. Example — objects in partition customerA or customerB, but not in environment=qa:

partition in (customerA, customerB),environment!=qa

The comma separator acts as a logical AND operator — all requirements must be satisfied simultaneously.

Memory anchor — when to use set-based

Use set-based when you need: an OR on values (in), checking key existence without caring about value (exists), or excluding multiple values at once (notin). Equality-based only handles single-value comparisons.

⚡ Quick Check — Set-based operators

The selector tier notin (frontend, backend) will match which Pods?

notin matches objects where the value is not in the set AND objects where the key is absent entirely. This mirrors the behavior of != in equality-based selectors.
⚡ Quick Check — exists operator

What does the selector partition (alone, without a value) do?

✓ A bare key (like partition) uses the exists operator — it selects all resources that have that label key, regardless of value. !partition inverts this, selecting resources that do NOT have the key.
Section 2.8 · PDF 5

API LIST and WATCH Filtering

For list and watch operations, you can specify label selectors to filter the sets of objects returned. The filter is passed as a query parameter in the URL.

Selector typeQuery param format
Equality-based ?labelSelector=environment%3Dproduction,tier%3Dfrontend
Set-based ?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29

kubectl examples

Both selector styles work with kubectl get pods -l:

# Equality-based kubectl get pods -l environment=production,tier=frontend # Set-based (more expressive — OR on values) kubectl get pods -l 'environment in (production),tier in (frontend)' # Set-based with OR operator on values kubectl get pods -l 'environment in (production, qa)' # Set-based with notin (restricts matching) kubectl get pods -l 'environment,environment notin (frontend)'
Set-based advantage

Set-based requirements are more expressive — they can implement the OR operator on values. For example environment in (production, qa) selects Pods in either environment — impossible with equality-based alone.

⚡ Quick Check — API Filtering

Which kubectl command selects Pods in EITHER production OR qa environment?

✓ The in operator handles OR on values. Writing two equality requirements with the same key would be contradictory (a key can't equal both at once). The || syntax doesn't exist in Kubernetes selectors.
Section 2.9 · PDF 5

Set References in API Objects

Some Kubernetes objects use label selectors to specify sets of other resources. Two important object types — Service and ReplicationController — use selectors to target Pods.

Service and ReplicationController

The set of Pods that a Service targets is defined by a label selector. Similarly, the ReplicationController uses a label selector to manage its Pods. Both define selectors in JSON/YAML using equality-based requirements only:

# JSON format "selector": { "component" : "redis" } # YAML format selector: component: redis

This selector is equivalent to component=redis or component in (redis).

Service & ReplicationController limitation

Label selectors for Service and ReplicationController are defined in JSON/YAML as simple maps — they only support equality-based requirements. To use set-based selectors, you need newer resource types.

Section 2.9a · PDF 5

matchLabels & matchExpressions

Newer resources — Job, Deployment, ReplicaSet, and DaemonSet — support set-based requirements via two fields: matchLabels and matchExpressions.

selector: matchLabels: component: redis matchExpressions: - { key: tier, operator: In, values: [cache] } - { key: environment, operator: NotIn, values: [dev] }
FieldTypeDescription
matchLabels map of {key,value} Each pair is equivalent to an equality requirement (key=value). Equivalent to an element in matchExpressions with operator In and single value.
matchExpressions list of requirements Each requirement has a key, an operator, and a values array. Valid operators: In, NotIn, Exists, DoesNotExist.
Values constraint

The values set must be non-empty for In and NotIn operators. All requirements from both matchLabels and matchExpressions are ANDed together — all must be satisfied for a match.

Selecting sets of nodes

One use case for selecting over labels is to constrain which nodes a Pod can schedule onto. This is done using node selection — see the node selection documentation for more information. The same label selector primitives apply for targeting node labels.

Memory anchor — which resources support what

Service & ReplicationController → equality-based only (JSON map).
Job, Deployment, ReplicaSet, DaemonSet → set-based via matchLabels + matchExpressions.
Both matchLabels and matchExpressions must ALL match (AND logic).

⚡ Quick Check — matchExpressions

In a ReplicaSet selector, matchLabels: {component: redis} is equivalent to which matchExpressions entry?

✓ A single matchLabels pair {key: value} is equivalent to a matchExpressions element with operator: In and values: [value]. The In operator with a single value behaves exactly like equality.
⚡ Quick Check — Resource capability

You need a selector that targets Pods with tier in (cache, memory). Which resource type(s) support this?

✓ Service and ReplicationController only support equality-based selectors (simple key=value maps). Set-based requirements like in require newer resource types that support matchExpressions.
Section 2.10 · PDF 6

Using Labels Effectively

You can apply a single label to any resource, but this is not always the best practice. There are many scenarios where multiple labels should be used to distinguish resource sets from one another.

Two label key conventions

app — included for convenience in manual queries and simple CLI usage.
app.kubernetes.io/name — follows the recommended Kubernetes labeling conventions and is better suited for tooling and automation.

Guestbook multi-tier example

A multi-tier application (like a guestbook) needs to distinguish frontend from backend, and different roles within backend. Using multiple labels enables slicing along any dimension:

# Frontend tier labels: app: guestbook app.kubernetes.io/name: guestbook tier: frontend # Redis master (backend) labels: app: guestbook tier: backend role: master # Redis replica (backend) labels: app: guestbook tier: backend role: replica

Slicing and dicing by any dimension

With multiple labels you can query across any dimension independently — without reorganizing resources:

# Show ALL pods with app/tier/role as columns kubectl get pods -Lapp -Ltier -Lrole # Filter only backend replicas (AND logic) kubectl get pods -lapp=guestbook,role=replica
NAMEAPPTIERROLE
guestbook-fe-4n1pbguestbookfrontend<none>
guestbook-redis-masterguestbookbackendmaster
guestbook-redis-replicaguestbookbackendreplica
my-nginx-divi2nginx<none><none>
Memory anchor — multi-label as a data cube

Think of labels as dimensions on a data cube. Each label key is a dimension (app, tier, role, environment). You can query any slice — frontend only, all backends, only replicas — without restructuring the cluster.

⚡ Quick Check — Effective labeling

In the guestbook example, how do you select ONLY the Redis replica Pods?

-lapp=guestbook,role=replica uses -l (filter) with AND logic. -ltier=backend would also return the master. -L is for displaying label values as columns, not filtering.
⚡ Quick Check — Label key convention

For a label used by automation tools and CI/CD pipelines, which key format is recommended?

app.kubernetes.io/name follows the recommended Kubernetes labeling conventions and is better suited for tooling and automation. The plain app key is for convenience in manual CLI queries.
Section 2.11 · PDF 6

Updating Labels

Sometimes you may want to relabel existing Pods and other resources before creating new ones. This can be done with kubectl label.

# Add/update label tier=fe on all Pods with app=nginx kubectl label pods -l app=nginx tier=fe # Confirmation output: pod/my-nginx-2035384211-j5fhi labeled pod/my-nginx-2035384211-u2c7e labeled pod/my-nginx-2035384211-u3t6x labeled

This first filters all Pods with app=nginx, then applies the label tier=fe to each of them.

Displaying label columns (-L)

Use -L (or --label-columns) to display label values as columns in the output:

# Show app=nginx pods with "tier" as a column kubectl get pods -l app=nginx -L tier
FlagPurposeExample
-lFilter/select resources by label (lowercase L)-l app=nginx
-LDisplay label value as output column (uppercase L)-L tier
-l vs -L — common confusion

-l (lowercase) = label selector — filters which resources are shown.
-L (uppercase) = label column — adds a column showing the value of that label.
They can be combined: kubectl get pods -l app=nginx -L tier

⚡ Quick Check — kubectl label

What does kubectl label pods -l app=nginx tier=fe do?

kubectl label modifies labels on existing resources. The -l app=nginx selector identifies which Pods to update, and tier=fe is the new label to add or overwrite on each.
Section 3 · PDF 7

Namespaces

In Kubernetes, namespaces provide a mechanism for isolating groups of resources within a single cluster. Names of resources need to be unique within a namespace, but not across namespaces.

Scope of namespace-based isolation

Namespace-based scoping applies only to namespaced objects (e.g. Deployments, Services). It does not apply to cluster-wide objects (e.g. StorageClass, Nodes, PersistentVolumes).

Isolation Name scoping Resource quota Multi-team
Section 3.1 · PDF 7

When to Use Multiple Namespaces

Namespaces are intended for use in environments with many users spread across multiple teams, or projects. For clusters with a few to tens of users, you should not need to create or think about namespaces at all.

Use namespaces when…Don't use namespaces when…
Many users / teams sharing a clusterSmall team, few resources
You need to divide cluster resources via resource quotaDistinguishing slightly different versions of the same software — use labels instead
You want name isolation across projectsNesting is needed (namespaces cannot be nested)
Labels vs Namespaces

It is not necessary to use multiple namespaces to separate slightly different resources, such as different versions of the same software. Use labels to distinguish resources within the same namespace.

Production tip

For a production cluster, consider not using the default namespace. Instead, make other namespaces and use those.

⚡ Quick Check — When to use namespaces

You have two versions of the same app (v1 and v2) running in the same cluster. Should you use separate namespaces?

✓ The docs explicitly state: it is NOT necessary to use namespaces to separate slightly different resources like different versions of the same software. Labels are the right tool for that.
Section 3.2 · PDF 7

Initial Namespaces

Kubernetes starts with four initial namespaces:

NamespacePurpose
defaultStart using the cluster without first creating a namespace. Not recommended for production.
kube-node-leaseHolds Lease objects associated with each node. Node leases allow kubelet to send heartbeats so the control plane can detect node failure.
kube-publicReadable by all clients (including unauthenticated). Reserved for cluster usage — resources visible/readable publicly throughout the whole cluster. Public aspect is only a convention, not a requirement.
kube-systemNamespace for objects created by the Kubernetes system itself.
Reserved prefix

Avoid creating namespaces with the prefix kube- — it is reserved for Kubernetes system namespaces.

⚡ Quick Check — Initial namespaces

Which namespace holds the Lease objects used for node heartbeats?

kube-node-lease holds Lease objects for each node. These allow kubelet to send heartbeats to the control plane — enabling node failure detection.
Section 3.3 · PDF 7

Working with Namespaces

Viewing namespaces

# List all namespaces kubectl get namespace NAME STATUS AGE default Active 1d kube-node-lease Active 1d kube-public Active 1d kube-system Active 1d

Setting namespace for a request

Use the --namespace flag to target a specific namespace for a single request:

# Run a pod in a specific namespace kubectl run nginx --image=nginx --namespace=<ns-name> # Get pods from a specific namespace kubectl get pods --namespace=<ns-name>

Setting the namespace preference

You can permanently save the namespace for all subsequent kubectl commands in a context:

# Set default namespace for current context kubectl config set-context --current --namespace=<ns-name> # Validate it kubectl config view --minify | grep namespace:
--namespace vs set-context

--namespace (or -n) — targets one namespace for a single command.
kubectl config set-context --current --namespace=... — permanently changes the default namespace for all subsequent commands in the current context.

⚡ Quick Check — Namespace flags

Which command permanently sets the default namespace for all subsequent kubectl commands?

kubectl config set-context --current --namespace=<ns> permanently updates the kubeconfig context to use that namespace by default. The --namespace flag only applies to a single command.
Section 3.4 · PDF 7

Namespaces and DNS

When you create a Service, it creates a corresponding DNS entry of the form:

<service-name>.<namespace-name>.svc.cluster.local

If a container only uses <service-name> (short name), it will resolve to the service local to its namespace. This is useful for using the same configuration across multiple namespaces such as Development, Staging, and Production.

To reach a service across namespaces, you must use the fully qualified domain name (FQDN).

DNS security warning

Creating namespaces with the same name as public top-level domains can cause Services to have DNS names that overlap with public DNS records. Workloads performing DNS lookups without a trailing dot will be redirected to those services, taking precedence over public DNS. Limit namespace creation privileges to trusted users.

Namespace names must be valid DNS labels

Namespace names must be valid RFC 1123 DNS labels — this is because they appear directly in DNS entries for Services.

⚡ Quick Check — Namespaces and DNS

A Pod in namespace "staging" uses the short name "my-svc" to call a service. Which service will it reach?

✓ Short service names resolve to the service local to the caller's namespace. A Pod in "staging" using "my-svc" reaches "my-svc.staging.svc.cluster.local". To reach a service in a different namespace, use the full FQDN.
Section 3.5 · PDF 7

Namespace Scope & Automatic Labelling

Not all objects are in a namespace

Most Kubernetes resources (Pods, Services, Deployments, ReplicationControllers, etc.) are namespaced. However, some low-level / cluster-wide resources are not:

Namespaced resourcesCluster-wide resources (not namespaced)
Pods, Services, DeploymentsNodes
ReplicationControllers, ReplicaSetsPersistentVolumes
ConfigMaps, SecretsStorageClass
Namespace objects themselves are NOT in a namespaceClusterRoles, ClusterRoleBindings
# List resources IN a namespace kubectl api-resources --namespaced=true # List resources NOT in a namespace (cluster-wide) kubectl api-resources --namespaced=false

Automatic labelling

Since Kubernetes 1.22 (stable), the control plane sets an immutable label kubernetes.io/metadata.name on all namespaces. The value of the label is the namespace name.

Memory anchor — namespaced vs cluster-wide

Namespaced: workload objects (Pods, Deployments, Services) — things that run or route.
Cluster-wide: infrastructure objects (Nodes, PersistentVolumes, StorageClass) — things that exist at the physical/cluster level.
Namespace objects themselves are also cluster-wide (they cannot be inside themselves).

⚡ Quick Check — Namespace scope

Which of these resources is NOT namespaced (cluster-wide)?

✓ PersistentVolumes are cluster-wide (not namespaced) — they represent physical storage infrastructure. Deployments, Services, and ConfigMaps are all namespaced objects.
⚡ Quick Check — Auto-labelling

What label does Kubernetes automatically set on all namespaces since v1.22?

kubernetes.io/metadata.name is set immutably on all namespaces by the control plane since Kubernetes 1.22 (stable). Its value is the namespace name itself.
Section 4 · PDF 8

Annotations

You can use Kubernetes annotations to attach arbitrary non-identifying metadata to objects. Clients such as tools and libraries can retrieve this metadata.

Labels vs Annotations

Labels — used to select objects and find collections that satisfy certain conditions.
Annotations — NOT used to identify and select objects. They store arbitrary metadata that is too large, structured, or non-identifying for labels.

Annotations, like labels, are key/value maps:

"metadata": { "annotations": { "key1" : "value1", "key2" : "value2" } }
Strings only

The keys and values in the annotation map must be strings. You cannot use numeric, boolean, list, or other types for either the keys or the values.

Non-identifying metadata Arbitrary size String values only Not selectable
Section 4.1 · PDF 8

Annotation Use Cases & Syntax

What to store in annotations

CategoryExamples
Declarative config fieldsFields managed by a config layer; distinguishes them from client defaults or auto-generated fields
Build / release infoTimestamps, release IDs, git branch, PR numbers, image hashes, registry address
Observability pointersPointers to logging, monitoring, analytics, or audit repositories
Debug infoClient library or tool info: name, version, build information
ProvenanceURLs of related objects from other ecosystem components
Rollout metadataLightweight rollout tool metadata: config or checkpoints
Contact infoPhone/pager numbers for persons responsible, or directory entries
User directivesDirectives from the end-user to implementations to modify behavior or engage non-standard features
Why not an external database?

Instead of annotations, you could store this information in an external database or directory — but that would make it much harder to produce shared client libraries and tools for deployment, management, introspection, and the like. Keeping metadata on the object keeps it co-located with the resource.

Annotation key syntax

Annotation keys have two segments: an optional prefix and a name, separated by /. Same rules as label keys:

SegmentRules
Name (required)≤63 chars; start/end with [a-z0-9A-Z]; dashes, underscores, dots between
Prefix (optional)DNS subdomain ≤253 chars followed by /. If omitted, key is private to user.

The kubernetes.io/ and k8s.io/ prefixes are reserved for Kubernetes core components. Automated system components that add annotations to end-user objects must specify a prefix.

Example manifest with annotation

apiVersion: v1 kind: Pod metadata: name: annotations-demo annotations: imageregistry: "https://hub.docker.com/" spec: containers: - name: nginx image: nginx:1.14.2
⚡ Quick Check — Labels vs Annotations

You want to store the git commit hash that produced a Pod's image. Should you use a label or an annotation?

✓ Git commit hashes are annotations. They are informational/audit metadata — you won't use them to select Pods or group resources. Labels are for identification and selection. Annotations hold the rest.
⚡ Quick Check — Annotation value types

Which of these annotation values is INVALID?

✓ Annotation values must be strings. The bare boolean true is invalid. However "true" (a string) is valid. Numbers, lists, and booleans cannot be used as annotation values.
Section 5 · PDF 8

Field Selectors

Field selectors let you select Kubernetes objects based on the value of one or more resource fields — not labels, but actual field values in the object's spec or status.

Field selectors are filters

Field selectors are essentially resource filters. By default, no selectors/filters are applied — meaning all resources of the specified type are selected. kubectl get pods and kubectl get pods --field-selector "" are equivalent.

Example queries

# Select Pods where status.phase=Running kubectl get pods --field-selector status.phase=Running # Select Services NOT in the default namespace kubectl get services --all-namespaces --field-selector metadata.namespace!=default

Common field selector examples:

metadata.name=my-service metadata.namespace!=default status.phase=Pending
⚡ Quick Check — Field vs Label selectors

What is the key difference between field selectors and label selectors?

✓ Field selectors filter by actual resource fields like status.phase, spec.nodeName, metadata.namespace. Label selectors filter by user-defined label key/value pairs. They are complementary, not interchangeable.
Section 5.1 · PDF 8

Supported Fields & Operators

Universal fields (all resource types)

All resource types support metadata.name and metadata.namespace. Using an unsupported field selector produces an error.

Per-kind supported fields

KindAdditional Supported Fields
Podspec.nodeName, spec.restartPolicy, spec.schedulerName, spec.serviceAccountName, spec.hostNetwork, status.phase, status.podIP, status.podIPs, status.nominatedNodeName
EventinvolvedObject.kind/namespace/name/uid/apiVersion/resourceVersion/fieldPath, reason, reportingComponent, source, type
Secrettype
Namespacestatus.phase
ReplicaSet / ReplicationControllerstatus.replicas
Jobstatus.successful
Nodespec.unschedulable
CertificateSigningRequestspec.signerName

Supported operators

Field selectors support =, == (same as =), and !=.

No set-based operators

Set-based operators (in, notin, exists) are NOT supported for field selectors. Only equality and inequality operators work.

Custom resources

All custom resource types support metadata.name and metadata.namespace. Additionally, the spec.versions[*].selectableFields field of a CustomResourceDefinition declares which other fields may be used in field selectors.

⚡ Quick Check — Supported operators

Which of these field selector queries is INVALID?

in is a set-based operator — it is NOT supported for field selectors. Only =, ==, and != are valid. This is different from label selectors which do support in.
Section 5.2 · PDF 8

Chained & Multi-type Field Selectors

Chaining field selectors

Like label selectors, field selectors can be chained with a comma (AND logic). This selects all Pods where status.phase is not Running AND spec.restartPolicy is Always:

kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always

Multiple resource types

Field selectors can be used across multiple resource types in one command. This selects all StatefulSets and Services that are not in the default namespace:

kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default
Memory anchor — field selectors summary

Field selectors = filter by field values (not labels). Operators: =, ==, != only (no set-based). Universal fields: metadata.name, metadata.namespace. Can chain with comma (AND). Can target multiple resource types. Empty selector = no filter = all resources.

⚡ Quick Check — Chained selectors

What does kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always return?

✓ Comma in field selectors = logical AND — same as label selectors. Both conditions must be true: phase is NOT Running AND restartPolicy IS Always.
Section 6 · PDF 9

Recommended Labels

A common set of labels allows tools to work interoperably, describing objects in a manner that all tools can understand. These recommended labels describe applications in a way that can be queried.

Shared prefix: app.kubernetes.io

All recommended labels share the app.kubernetes.io prefix. Labels without a prefix are private to users. The shared prefix ensures that shared labels do not interfere with custom user labels.
These are recommended, not required for any core tooling.

The 6 recommended label keys

KeyDescriptionExample
app.kubernetes.io/nameThe name of the applicationmysql
app.kubernetes.io/instanceA unique name identifying the instance of an applicationmysql-abcxyz
app.kubernetes.io/versionThe current version (SemVer 1.0, revision hash, etc.)5.7.21
app.kubernetes.io/componentThe component within the architecturedatabase
app.kubernetes.io/part-ofThe name of a higher level application this one is part ofwordpress
app.kubernetes.io/managed-byThe tool being used to manage the operation of an applicationHelm
Application vs Instance

name = the type of application (e.g. wordpress).
instance = the unique name of this specific deployment (e.g. wordpress-abcxyz).
This matters when the same application is installed multiple times — WordPress can be installed twice; each has the same name but a different instance.

StatefulSet example

apiVersion: apps/v1 kind: StatefulSet metadata: labels: app.kubernetes.io/name: mysql app.kubernetes.io/instance: mysql-abcxyz app.kubernetes.io/version: "5.7.21" app.kubernetes.io/component: database app.kubernetes.io/part-of: wordpress app.kubernetes.io/managed-by: Helm
⚡ Quick Check — Recommended labels

Which label indicates that a MySQL StatefulSet is part of a larger WordPress application?

app.kubernetes.io/part-of indicates the higher-level application this component belongs to. The MySQL database is a part of the wordpress application. name would be "mysql" (the component's own name).
Section 6.1 · PDF 9

Recommended Labels — Examples

Simple stateless service (Deployment + Service)

# Deployment app.kubernetes.io/name: myservice app.kubernetes.io/instance: myservice-abcxyz # Service (same labels) app.kubernetes.io/name: myservice app.kubernetes.io/instance: myservice-abcxyz

Web application with database (WordPress + MySQL via Helm)

In a more complex app, each component carries labels for both itself and the broader application it belongs to:

# WordPress Deployment app.kubernetes.io/name: wordpress app.kubernetes.io/instance: wordpress-abcxyz app.kubernetes.io/version: "4.9.4" app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: server app.kubernetes.io/part-of: wordpress # MySQL StatefulSet (different name/version, same part-of) app.kubernetes.io/name: mysql app.kubernetes.io/instance: mysql-abcxyz app.kubernetes.io/version: "5.7.21" app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: database app.kubernetes.io/part-of: wordpress
Key insight — part-of ties the app together

Both WordPress and MySQL have different name, instance, and version, but they share part-of: wordpress. This lets tools discover all components of the WordPress application with a single label selector: app.kubernetes.io/part-of=wordpress.

⚡ Quick Check — name vs instance

WordPress is installed twice in the same cluster. What distinguishes the two installations?

✓ Both installations share name: wordpress (same application type). They differ by instance — each instance gets a unique name (often including a random suffix). This enables tools to distinguish and manage multiple instances of the same application.
Section 7 · PDF 9

Storage Versions

The Kubernetes API server stores objects in an etcd-compatible backing store. Each object is serialized using a particular version of that API type — this is called the storage version.

Automatic conversion

The Kubernetes API relies on automatic conversion. If you have a HorizontalPodAutoscaler with v1 and v2 APIs, you can interact with it using either version — Kubernetes converts each API call so clients don't see what version is actually serialized.

One storage version per resource at a time

The same API may have multiple storage versions, but a single object must only have one storage version at any time. The API Server knows all binary encodings and can convert between stored versions dynamically.

OperationBehavior
ReadsConvert stored data to the API representation — old storage versions can sit indefinitely as long as no updates occur
WritesConvert the object to the current (new) storage version representation upon update/create
Version vs Storage Version

The version of an object (e.g. v1alpha1 vs v1beta1) is separate from the storage version. A v1alpha1 and v1beta1 object for the same resource will be encoded the same in storage as long as the storage version hasn't changed between them.

⚡ Quick Check — Storage versions

An object was stored using an old storage version. It has not been updated. When you READ it via the API, what happens?

Reads auto-convert — the API server converts the stored data to the current API representation. The object remains at the old storage version in etcd (no migration). Only writes (create/update) trigger migration to the current storage version.
Section 7.1 · PDF 9

CRD Storage Versions & Encryption at Rest

Storage versions for custom resources

For Custom Resources (CRDs), a certain version must be explicitly set as the storage version. The schema defined by that version is used as the encoding in the storage layer.

versions: - name: v1beta1 served: true storage: true # ← this is the storage version schema: ... - name: v1 served: true storage: false # ← not the storage version schema: ...
One storage version only

One and only one version may be marked storage: true. Setting two versions as the storage version is considered invalid — it would mean two data schemas are valid ways to store the same object simultaneously. Only updating or creating will use the newly defined storage version; watching or getting an existing object will just convert from the old version.

Storage versions and encryption at rest

There are tools to encrypt at-rest storage, especially for cluster Secrets. This means the actual stored data is encrypted. The API Server must decrypt the data as it retrieves it, and must have the key for that storage version to decode the object properly.

The storage version is more than just the binary encoding — as long as what is stored can be converted into the API object, it can be used as a storage version. This matters for encryption because changing the storage version changes how the API server decodes the stored bytes.

⚡ Quick Check — CRD storage version

In a CRD with two versions (v1beta1 and v1), v1beta1 is marked storage: true. What is the effect on the "time" field that only exists in the v1 schema?

✓ The storage version's schema defines what can be persisted. If v1beta1 is the storage version and its schema doesn't include time, then the time field cannot be stored — even if v1 supports it. This is explicitly noted in the docs: the v1 API object would never be able to store the time field since it's not part of the storage definition.
Section 8 · PDF 10

The Kubernetes API

The Kubernetes API lets you query and manipulate the state of objects in Kubernetes. The core of the control plane is the API server — users, cluster components, and external tools all communicate through it.

MechanismPurpose
Discovery APIBrief summary: name, scope, URL, verbs. Not full schema.
OpenAPI DocumentFull OpenAPI v2 and v3 schemas for all endpoints.
Section 8.1 · PDF 10

Discovery API

Publishes a summary of all resources: name, scope, endpoint URL, supported verbs, alternative names, group/version/kind. It is a brief summary — not a full schema. For full schemas, use the OpenAPI document.

ModeEndpointsFeature State
Aggregated/api and /apisStable v1.30 — drastically reduces requests; requires special Accept header
UnaggregatedOne endpoint per group/versionDefault without Accept header; root endpoints act as discovery for downstream docs
kubectl uses Discovery API

kubectl fetches and caches the API spec for command-line completion and cluster-awareness.

⚡ Quick Check — Discovery API

What does the Discovery API provide for each resource? (choose best answer)

✓ The Discovery API is a brief summary — not a full schema. For field definitions and validation, refer to the OpenAPI document.
Section 8.2 · PDF 10

OpenAPI & Protobuf Serialization

OpenAPI v2OpenAPI v3
Endpoint/openapi/v2/openapi/v3 + /openapi/v3/apis/<group>/<version>?hash=<h>
StateStableStable since v1.27, enabled by default
FidelityLossy — drops default, nullable, oneOfLossless — complete specification

OpenAPI v3 URLs are immutable (hash-based) for client-side caching (Cache-Control: immutable, Expires 1 year). Obsolete URLs return a redirect.

OpenAPI validation is incomplete

OpenAPI schemas may not capture all validation. Use kubectl apply --dry-run=server for complete server-side validation including admission checks.

Protobuf serialization — alternative binary format, primarily for intra-cluster use. Persistence: Kubernetes stores serialized state in etcd. Kubernetes 1.36 publishes OpenAPI v2 and v3 — no plans for 3.1.

⚡ Quick Check — OpenAPI versions

Why is OpenAPI v3 preferred over v2?

✓ OpenAPI v3 is lossless — includes all paths, resources, and extensibility components. v2 is limited by format constraints and drops certain fields.
Section 8.3 · PDF 10

API Groups, Versioning & Changes

Kubernetes supports multiple API versions at different paths. Versioning is at the API level (not resource/field level). The API server converts transparently — all versions represent the same persisted data.

# Core group /api/v1 # Named groups /apis/rbac.authorization.k8s.io/v1alpha1 /apis/apps/v1
LevelCompatibility guaranteeNotes
GA (v1)Strong — Kubernetes commits to compatibility for official APIsAlso preserves beta-persisted data
BetaData preserved; must transition before deprecation endsBest to migrate during deprecation period — both versions served simultaneously
AlphaNo guarantee — may break incompatiblyCheck release notes; may need to delete all alpha objects before cluster upgrade
API changes philosophy

Kubernetes aims NOT to break compatibility with existing clients. New resources and fields can be added frequently. Removing resources or fields requires following the API deprecation policy.

⚡ Quick Check — API stability

When MUST you migrate from a beta API?

✓ Migrate during the deprecation window — both versions are served simultaneously. Once the beta is removed, only the GA version works.
Section 8.4 · PDF 10

API Extension

The Kubernetes API can be extended in two ways:

MechanismDescription
Custom Resources (CRDs)Declaratively define new resource types — no additional code needed; API server serves them natively.
Aggregation LayerImplement a custom extension API server; main API server proxies requests to it.
Memory anchor

CRDs = declarative, no code, simpler. Aggregation layer = custom code, more powerful/flexible.

⚡ Quick Check — API Extension

What are the two mechanisms to extend the Kubernetes API?

✓ CRDs (declarative new resource types) and the Aggregation Layer (custom API server). Both allow the Kubernetes API to serve new resource types.
⚙️
Quiz Settings
All topics · Easy · 5 questions
PDF 1 · Components
PDF 2 · Objects
PDF 5 · Set-based & API
PDF 6 · Labels in Practice
PDF 7 · Namespaces
PDF 8 · Annotations & Fields
PDF 9 · Rec. Labels & Storage
PDF 10 · The Kubernetes API
Difficulty
Questions per session
Ready to Test Your Knowledge?
Select topics and difficulty on the left, then click Generate Quiz to get a random set of questions.
Questions include: single choice, multi-select, code reading, and free-response